library(tsibbledata)
library(tidyverse)
Registered S3 methods overwritten by 'dbplyr':
method from
print.tbl_lazy
print.tbl_sql
── Attaching packages ──────────────────────────────────────────────── tidyverse 1.3.2 ──✔ ggplot2 3.3.6 ✔ purrr 0.3.4
✔ tibble 3.1.8 ✔ dplyr 1.0.9
✔ tidyr 1.2.0 ✔ stringr 1.4.0
✔ readr 2.1.2 ✔ forcats 0.5.1── Conflicts ─────────────────────────────────────────────────── tidyverse_conflicts() ──
✖ dplyr::filter() masks stats::filter()
✖ dplyr::lag() masks stats::lag()
library(lubridate)
Attaching package: ‘lubridate’
The following objects are masked from ‘package:base’:
date, intersect, setdiff, union
library(tsibble)
Attaching package: ‘tsibble’
The following object is masked from ‘package:lubridate’:
interval
The following objects are masked from ‘package:base’:
intersect, setdiff, union
nyc_bikes_df <- nyc_bikes
What is the pattern of bike hires over time (e.g. within a year,
month, week, or day)? Do bike hire patterns differ between bike rider
demographics? (e.g. gender, type of trip, age) Any other insights?
You will probably want to use the data in column start_time to create
date, month and year columns. Summarising the data by aggregating hire
counts by different measures of time (e.g. year, quarter, month, day)
and then visualising the results is probably a good idea When grouping
time series data (tsibble), you need to use index_by instead of
group_by
nyc_bikes_short <- nyc_bikes_df %>%
select(start_time, stop_time, birth_year, gender, type) %>%
mutate(year = year(start_time),
month = month(start_time, label = TRUE),
day = as.Date(start_time),
wday = wday(start_time,label = TRUE),
week = week(start_time),
time_ride = stop_time - start_time,
age = as.numeric(year - birth_year))
nyc_bikes_short
year/month/week/day pattern
bike_year <-nyc_bikes_short%>%
index_by(year) %>%
summarise(p90 = quantile(time_ride, probs=0.9, na.rm=TRUE))
bike_year
nyc_bikes_short %>%
mutate(time_ride = as.numeric(time_ride)) %>%
filter(time_ride < 17.94614) %>%
ggplot() +
aes(as.factor(year), as.numeric(time_ride))+
geom_boxplot() +
labs(x = "\nYear",
y = "time_ride",
title = "Distribution of riding time in 2018(90%)",
subtitle = "Data from citibike NYC\n")

nyc_bikes_short %>%
ggplot()+
aes(as.factor(year), as.numeric(time_ride)) %>%
geom_boxplot()+
labs(x = "\nYear",
y = "time_ride",
title = "Distribution of riding time in 2018(100%)",
subtitle = "Data from citiBike NYC\n")

#the outliers are too crazy so I only included the 90% of the data to give
#a brief idea of how the ride time is like in the year of 2018.
bike_month <- nyc_bikes_short%>%
index_by(month) %>%
summarise(ride_time_mean = mean(time_ride, na.rm = TRUE))
bike_month
bike_month %>%
ggplot(aes(month, as.numeric(ride_time_mean)))+
geom_point()+
geom_line(group = 1)+
labs(
x="Month",
y = "Average Riding Time",
title = "Average riding time for each month",
subtitle = "Data from 2018 citibike NYC\n"
)

bike_wday <- nyc_bikes_short%>%
index_by(wday) %>%
summarise(ride_time_mean = mean(time_ride, na.rm = TRUE))
bike_wday
bike_wday %>%
ggplot(aes(wday, ride_time_mean))+
geom_point()+
geom_line(group = 1)+
labs(
x="Weekdays",
y = "Average Riding Time",
title = "Average riding time for each day of week",
subtitle = "Data from 2018 citibike NYC\n"
)

bike_day <- nyc_bikes_short%>%
index_by(day) %>%
summarise(ride_time_mean = mean(time_ride, na.rm = TRUE))
bike_day
bike_day %>%
ggplot(aes(day, as.numeric(ride_time_mean)))+
geom_line()+
coord_trans(y = "log10")+
labs(
x="Days",
y = "Average Riding Time(log_scale)",
title = "Average riding time for each day",
subtitle = "Data from 2018 citibike NYC\n"
)

week
bike_week <- nyc_bikes_short%>%
index_by(week) %>%
summarise(ride_time_mean = mean(time_ride, na.rm = TRUE))
bike_week
bike_week %>%
ggplot(aes(week, as.numeric(ride_time_mean)))+
geom_point()+
geom_line(group = 1)+
scale_x_continuous(breaks = seq(0,52,5))+
coord_trans(y = "log10")+
labs(
x="Weeks in the year",
y = "Average Riding Time(log scale)",
title = "Average riding time for each week",
subtitle = "Data from 2018 citibike NYC\n"
)

#42 and 46 something to check
#OCT 15 -21
#nov 12 -18
##gender-year
nyc_bikes_short %>%
mutate(time_ride = as.numeric(time_ride)) %>%
filter(time_ride < 17.94614) %>%
ggplot() +
aes(as.factor(year), as.numeric(time_ride))+
geom_boxplot(aes(col = gender)) +
labs(x = "\nYear",
y = "time_ride",
title = "Distribution of ride time in 2018(90%)",
subtitle = "for each gender\n")

gender month
nyc_bikes_short %>%
group_by(gender) %>%
index_by(month) %>%
summarise(mean_time_ride = mean(time_ride)) %>%
ggplot(aes(month, as.numeric(mean_time_ride)))+
facet_grid(~gender)+
geom_point(aes(col = gender))+
geom_line(group = 1)+
theme(axis.text.x = element_text(angle = 90, vjust = 0.5, hjust=1))

labs(
x="Month",
y = "Average Riding Time",
title = "Average riding time for each month",
subtitle = "for each gender NYC\n"
)
$x
[1] "Month"
$y
[1] "Average Riding Time"
$title
[1] "Average riding time for each month"
$subtitle
[1] "for each gender NYC\n"
attr(,"class")
[1] "labels"
gender week
nyc_bikes_short %>%
group_by(gender) %>%
index_by(week) %>%
summarise(mean_time_ride = mean(time_ride)) %>%
ggplot(aes(week, as.numeric(mean_time_ride)))+
facet_wrap(~gender,ncol =1, scales = "free_y")+
geom_point(aes(col = gender))+
geom_line(group = 1)+
scale_x_continuous(breaks = seq(0,52,5))+
labs(
x="Week",
y = "Average Riding Time",
title = "Average riding time for each month",
subtitle = "for each gender NYC\n"
)

gender weekdays
nyc_bikes_short %>%
group_by(gender) %>%
index_by(wday) %>%
summarise(mean_time_ride = mean(time_ride)) %>%
ggplot(aes(wday, as.numeric(mean_time_ride)))+
facet_wrap(~gender,ncol =1, scales = "free_y")+
geom_point(aes(col = gender))+
geom_line(aes(col = gender),group = 1)+
labs(
x="Weekday",
y = "Average Riding Time",
title = "Average riding time for each weekdays",
subtitle = "for each gender NYC\n"
)

nyc_bikes_short <- nyc_bikes_short %>% mutate(
age_group = case_when(age < 18 ~ "Under 18",
age < 30 ~"18 to 30",
age < 60 ~"30 to 60",
TRUE ~"60 and above")
)
age_year
nyc_bikes_short %>%
mutate(time_ride = as.numeric(time_ride)) %>%
filter(time_ride < 17.94614) %>%
ggplot() +
aes(as.factor(age_group), as.numeric(time_ride))+
geom_boxplot(aes(col = age_group)) +
labs(x = "\nAge Group",
y = "Riding Time",
col = "Age Group",
title = "Distribution of ride time in 2018",
subtitle = "with 90% of the data\n")

age month
nyc_bikes_short %>%
group_by(age_group) %>%
index_by(month) %>%
summarise(mean_time_ride = mean(time_ride)) %>%
ggplot(aes(month, as.numeric(mean_time_ride)))+
facet_wrap(~age_group, ncol = 1, scales = "free_y")+
geom_point(aes(col = age_group))+
geom_line(group = 1)+
theme(axis.text.x = element_text(angle = 90, vjust = 0.5, hjust=1))

labs(
x="Month",
y = "Average Riding Time",
title = "Average riding time for each month",
subtitle = "for each age_group NYC\n"
)
$x
[1] "Month"
$y
[1] "Average Riding Time"
$title
[1] "Average riding time for each month"
$subtitle
[1] "for each age_group NYC\n"
attr(,"class")
[1] "labels"
age weekday
nyc_bikes_short %>%
group_by(age_group) %>%
index_by(wday) %>%
summarise(mean_time_ride = mean(time_ride)) %>%
ggplot(aes(wday, as.numeric(mean_time_ride)))+
facet_wrap(~age_group,ncol =1, scales = "free_y")+
geom_point(aes(col = age_group), size = 2)+
geom_line(aes(col = age_group),group = 1)+
labs(
x="Weekday",
y = "Average Riding Time",
col = "Age Group",
title = "Average riding time for each weekdays",
subtitle = "for each age group \n"
)

nyc_bikes_short %>%
group_by(age_group) %>%
index_by(week) %>%
summarise(mean_time_ride = mean(time_ride)) %>%
ggplot(aes(week, as.numeric(mean_time_ride)))+
facet_wrap(~age_group,ncol =1, scales = "free_y")+
geom_point(aes(col = age_group))+
geom_line(group = 1)+
scale_x_continuous(breaks = seq(0,52,5))+
labs(
x="Week",
y = "Average Riding Time",
col = "Age Group",
title = "Average riding time for each week",
subtitle = "for each age group\n"
)

library(leaflet)
Registered S3 method overwritten by 'htmlwidgets':
method from
print.htmlwidget tools:rstudio
nyc_bikes_df %>%
filter(bike_id == "26301") %>%
leaflet() %>%
addTiles() %>%
addMarkers(
lng = ~start_long,
lat = ~start_lat,
clusterOptions = markerClusterOptions()
)
nyc_bikes_df %>%
filter(bike_id == "29477") %>%
leaflet() %>%
addTiles() %>%
addMarkers(
lng = ~start_long,
lat = ~start_lat,
clusterOptions = markerClusterOptions()
)
nyc_bikes_df %>%
mutate(week = week(start_time)) %>%
filter(week == 46) %>%
leaflet() %>%
addTiles() %>%
addMarkers(
lng = ~start_long,
lat = ~start_lat,
clusterOptions = markerClusterOptions()
)
nyc_bikes_df %>%
mutate(week = week(start_time)) %>%
filter(week == 42) %>%
leaflet() %>%
addTiles() %>%
addMarkers(
lng = ~end_long,
lat = ~end_lat,
clusterOptions = markerClusterOptions()
)
near to stations
nyc_bikes_short %>%
group_by(day) %>%
summarise(mean = mean(time_ride)) %>%
arrange(desc(mean))
Warning: Current temporal ordering may yield unexpected results.
ℹ Suggest to sort by `day`, `start_time` first.
We’re mid-way through Women’s Bike Month! october Did you know only a
quarter of all bike trips in the U.S. are taken by women? At Citi Bike,
we’re dedicated to changing this. This month we’re giving all new riders
their first trip free using code GIRLUP18, and donating $1 from each of
these rides to Girl Up’s SchoolCycle program to help provide bikes to
girls around the world so they can safely access education. Join us in
encouraging more ladies to get on bikes and give back to a great cause
while doing it.
nyc_bikes_df %>%
mutate(week = week(start_time)) %>%
filter(week == 4) %>%
leaflet() %>%
addTiles() %>%
addMarkers(
lng = ~end_long,
lat = ~end_lat,
clusterOptions = markerClusterOptions()
)
```
LS0tCnRpdGxlOiAiUiBOb3RlYm9vayIKb3V0cHV0OiBodG1sX25vdGVib29rCi0tLQpgYGB7cn0KbGlicmFyeSh0c2liYmxlZGF0YSkKbGlicmFyeSh0aWR5dmVyc2UpCmxpYnJhcnkobHVicmlkYXRlKQpsaWJyYXJ5KHRzaWJibGUpCm55Y19iaWtlc19kZiA8LSBueWNfYmlrZXMKYGBgCgpXaGF0IGlzIHRoZSBwYXR0ZXJuIG9mIGJpa2UgaGlyZXMgb3ZlciB0aW1lIChlLmcuIHdpdGhpbiBhIHllYXIsIG1vbnRoLCB3ZWVrLCBvciBkYXkpPwpEbyBiaWtlIGhpcmUgcGF0dGVybnMgZGlmZmVyIGJldHdlZW4gYmlrZSByaWRlciBkZW1vZ3JhcGhpY3M/IChlLmcuIGdlbmRlciwgdHlwZSBvZiB0cmlwLCBhZ2UpCkFueSBvdGhlciBpbnNpZ2h0cz8KCllvdSB3aWxsIHByb2JhYmx5IHdhbnQgdG8gdXNlIHRoZSBkYXRhIGluIGNvbHVtbiBzdGFydF90aW1lIHRvIGNyZWF0ZSBkYXRlLCBtb250aCBhbmQgeWVhciBjb2x1bW5zLgpTdW1tYXJpc2luZyB0aGUgZGF0YSBieSBhZ2dyZWdhdGluZyBoaXJlIGNvdW50cyBieSBkaWZmZXJlbnQgbWVhc3VyZXMgb2YgdGltZSAoZS5nLiB5ZWFyLCBxdWFydGVyLCBtb250aCwgZGF5KSBhbmQgdGhlbiB2aXN1YWxpc2luZyB0aGUgcmVzdWx0cyBpcyBwcm9iYWJseSBhIGdvb2QgaWRlYQpXaGVuIGdyb3VwaW5nIHRpbWUgc2VyaWVzIGRhdGEgKHRzaWJibGUpLCB5b3UgbmVlZCB0byB1c2UgaW5kZXhfYnkgaW5zdGVhZCBvZiBncm91cF9ieQpgYGB7cn0KbnljX2Jpa2VzX3Nob3J0IDwtIG55Y19iaWtlc19kZiAlPiUgCiAgc2VsZWN0KHN0YXJ0X3RpbWUsIHN0b3BfdGltZSwgYmlydGhfeWVhciwgZ2VuZGVyLCB0eXBlKSAlPiUgCiAgbXV0YXRlKHllYXIgPSB5ZWFyKHN0YXJ0X3RpbWUpLAogICAgICAgICBtb250aCA9IG1vbnRoKHN0YXJ0X3RpbWUsIGxhYmVsID0gVFJVRSksCiAgICAgICAgIGRheSA9IGFzLkRhdGUoc3RhcnRfdGltZSksCiAgICAgICAgIHdkYXkgID0gd2RheShzdGFydF90aW1lLGxhYmVsID0gVFJVRSksCiAgICAgICAgIHdlZWsgPSB3ZWVrKHN0YXJ0X3RpbWUpLAogICAgICAgICB0aW1lX3JpZGUgPSBzdG9wX3RpbWUgLSBzdGFydF90aW1lLAogICAgICAgICBhZ2UgPSBhcy5udW1lcmljKHllYXIgLSBiaXJ0aF95ZWFyKSkKbnljX2Jpa2VzX3Nob3J0CmBgYAoKeWVhci9tb250aC93ZWVrL2RheSBwYXR0ZXJuCgpgYGB7cn0KYmlrZV95ZWFyIDwtbnljX2Jpa2VzX3Nob3J0JT4lCiAgaW5kZXhfYnkoeWVhcikgJT4lCiAgc3VtbWFyaXNlKHA5MCA9IHF1YW50aWxlKHRpbWVfcmlkZSwgcHJvYnM9MC45LCBuYS5ybT1UUlVFKSkKYmlrZV95ZWFyCgogbnljX2Jpa2VzX3Nob3J0ICU+JSAKICBtdXRhdGUodGltZV9yaWRlID0gYXMubnVtZXJpYyh0aW1lX3JpZGUpKSAlPiUgCiAgZmlsdGVyKHRpbWVfcmlkZSA8IDE3Ljk0NjE0KSAlPiUgCmdncGxvdCgpICsgCiAgYWVzKGFzLmZhY3Rvcih5ZWFyKSwgYXMubnVtZXJpYyh0aW1lX3JpZGUpKSsKICBnZW9tX2JveHBsb3QoKSArIAogIGxhYnMoeCA9ICJcblllYXIiLAogICAgIHkgPSAidGltZV9yaWRlIiwKICAgICB0aXRsZSA9ICJEaXN0cmlidXRpb24gb2YgcmlkaW5nIHRpbWUgaW4gMjAxOCg5MCUpIiwKICAgICBzdWJ0aXRsZSA9ICJEYXRhIGZyb20gY2l0aWJpa2UgTllDXG4iKQoKCm55Y19iaWtlc19zaG9ydCAlPiUgCiAgZ2dwbG90KCkrCiAgYWVzKGFzLmZhY3Rvcih5ZWFyKSwgYXMubnVtZXJpYyh0aW1lX3JpZGUpKSAlPiUgCiAgZ2VvbV9ib3hwbG90KCkrCiAgbGFicyh4ID0gIlxuWWVhciIsCiAgICAgeSA9ICJ0aW1lX3JpZGUiLAogICAgIHRpdGxlID0gIkRpc3RyaWJ1dGlvbiBvZiByaWRpbmcgdGltZSBpbiAyMDE4KDEwMCUpIiwKICAgICBzdWJ0aXRsZSA9ICJEYXRhIGZyb20gY2l0aUJpa2UgTllDXG4iKQogI3RoZSBvdXRsaWVycyBhcmUgdG9vIGNyYXp5IHNvIEkgb25seSBpbmNsdWRlZCB0aGUgOTAlIG9mIHRoZSBkYXRhIHRvIGdpdmUgCiNhIGJyaWVmIGlkZWEgb2YgaG93IHRoZSByaWRlIHRpbWUgaXMgbGlrZSBpbiB0aGUgeWVhciBvZiAyMDE4LiAKYGBgCmBgYHtyfQpiaWtlX21vbnRoIDwtIG55Y19iaWtlc19zaG9ydCU+JSAKICBpbmRleF9ieShtb250aCkgJT4lIAogIHN1bW1hcmlzZShyaWRlX3RpbWVfbWVhbiA9IG1lYW4odGltZV9yaWRlLCBuYS5ybSA9IFRSVUUpKQoKYmlrZV9tb250aAoKYmlrZV9tb250aCAlPiUgCiAgZ2dwbG90KGFlcyhtb250aCwgYXMubnVtZXJpYyhyaWRlX3RpbWVfbWVhbikpKSsKICBnZW9tX3BvaW50KCkrCiAgZ2VvbV9saW5lKGdyb3VwID0gMSkrCiAgbGFicygKICAgIHg9Ik1vbnRoIiwKICAgIHkgPSAiQXZlcmFnZSBSaWRpbmcgVGltZSIsCiAgICB0aXRsZSA9ICJBdmVyYWdlIHJpZGluZyB0aW1lIGZvciBlYWNoIG1vbnRoIiwKICAgIHN1YnRpdGxlID0gIkRhdGEgZnJvbSAyMDE4IGNpdGliaWtlIE5ZQ1xuIgogICkKCmBgYAoKYGBge3J9CmJpa2Vfd2RheSA8LSBueWNfYmlrZXNfc2hvcnQlPiUgCiAgaW5kZXhfYnkod2RheSkgJT4lIAogIHN1bW1hcmlzZShyaWRlX3RpbWVfbWVhbiA9IG1lYW4odGltZV9yaWRlLCBuYS5ybSA9IFRSVUUpKQoKYmlrZV93ZGF5CgogYmlrZV93ZGF5ICU+JSAKICBnZ3Bsb3QoYWVzKHdkYXksIHJpZGVfdGltZV9tZWFuKSkrCiAgZ2VvbV9wb2ludCgpKwogIGdlb21fbGluZShncm91cCA9IDEpKwogICBsYWJzKAogICAgeD0iV2Vla2RheXMiLAogICAgeSA9ICJBdmVyYWdlIFJpZGluZyBUaW1lIiwKICAgIHRpdGxlID0gIkF2ZXJhZ2UgcmlkaW5nIHRpbWUgZm9yIGVhY2ggZGF5IG9mIHdlZWsiLAogICAgc3VidGl0bGUgPSAiRGF0YSBmcm9tIDIwMTggY2l0aWJpa2UgTllDXG4iCiAgKQpgYGAKYGBge3J9CmJpa2VfZGF5IDwtIG55Y19iaWtlc19zaG9ydCU+JSAKICBpbmRleF9ieShkYXkpICU+JSAKICBzdW1tYXJpc2UocmlkZV90aW1lX21lYW4gPSBtZWFuKHRpbWVfcmlkZSwgbmEucm0gPSBUUlVFKSkKCmJpa2VfZGF5CgpiaWtlX2RheSAlPiUgCiAgZ2dwbG90KGFlcyhkYXksIGFzLm51bWVyaWMocmlkZV90aW1lX21lYW4pKSkrCiAgZ2VvbV9saW5lKCkrCiAgY29vcmRfdHJhbnMoeSA9ICJsb2cxMCIpKwogIGxhYnMoCiAgICB4PSJEYXlzIiwKICAgIHkgPSAiQXZlcmFnZSBSaWRpbmcgVGltZShsb2dfc2NhbGUpIiwKICAgIHRpdGxlID0gIkF2ZXJhZ2UgcmlkaW5nIHRpbWUgZm9yIGVhY2ggZGF5IiwKICAgIHN1YnRpdGxlID0gIkRhdGEgZnJvbSAyMDE4IGNpdGliaWtlIE5ZQ1xuIgogICkKYGBgCndlZWsgCmBgYHtyfQpiaWtlX3dlZWsgPC0gbnljX2Jpa2VzX3Nob3J0JT4lIAogIGluZGV4X2J5KHdlZWspICU+JSAKICBzdW1tYXJpc2UocmlkZV90aW1lX21lYW4gPSBtZWFuKHRpbWVfcmlkZSwgbmEucm0gPSBUUlVFKSkKCmJpa2Vfd2VlawoKYmlrZV93ZWVrICU+JSAKICBnZ3Bsb3QoYWVzKHdlZWssIGFzLm51bWVyaWMocmlkZV90aW1lX21lYW4pKSkrCiAgZ2VvbV9wb2ludCgpKwogIGdlb21fbGluZShncm91cCA9IDEpKwogICBzY2FsZV94X2NvbnRpbnVvdXMoYnJlYWtzID0gc2VxKDAsNTIsNSkpKwogIGNvb3JkX3RyYW5zKHkgPSAibG9nMTAiKSsKICBsYWJzKAogICAgeD0iV2Vla3MgaW4gdGhlIHllYXIiLAogICAgeSA9ICJBdmVyYWdlIFJpZGluZyBUaW1lKGxvZyBzY2FsZSkiLAogICAgdGl0bGUgPSAiQXZlcmFnZSByaWRpbmcgdGltZSBmb3IgZWFjaCB3ZWVrIiwKICAgIHN1YnRpdGxlID0gIkRhdGEgZnJvbSAyMDE4IGNpdGliaWtlIE5ZQ1xuIgogICkKIzQyIGFuZCA0NiBzb21ldGhpbmcgdG8gY2hlY2sgCiNPQ1QgMTUgLTIxCiNub3YgMTIgLTE4CmBgYAoKCiMjZ2VuZGVyLXllYXIKYGBge3J9CiBueWNfYmlrZXNfc2hvcnQgJT4lIAogIG11dGF0ZSh0aW1lX3JpZGUgPSBhcy5udW1lcmljKHRpbWVfcmlkZSkpICU+JSAKICBmaWx0ZXIodGltZV9yaWRlIDwgMTcuOTQ2MTQpICU+JSAKZ2dwbG90KCkgKyAKICBhZXMoYXMuZmFjdG9yKHllYXIpLCBhcy5udW1lcmljKHRpbWVfcmlkZSkpKwogIGdlb21fYm94cGxvdChhZXMoY29sID0gZ2VuZGVyKSkgKyAKICBsYWJzKHggPSAiXG5ZZWFyIiwKICAgICB5ID0gInRpbWVfcmlkZSIsCiAgICAgdGl0bGUgPSAiRGlzdHJpYnV0aW9uIG9mIHJpZGUgdGltZSBpbiAyMDE4KDkwJSkiLAogICAgIHN1YnRpdGxlID0gImZvciBlYWNoIGdlbmRlclxuIikKCmBgYApnZW5kZXIgbW9udGgKYGBge3J9Cm55Y19iaWtlc19zaG9ydCAlPiUgCiAgZ3JvdXBfYnkoZ2VuZGVyKSAlPiUgCiAgaW5kZXhfYnkobW9udGgpICU+JSAKICBzdW1tYXJpc2UobWVhbl90aW1lX3JpZGUgPSBtZWFuKHRpbWVfcmlkZSkpICU+JSAKICBnZ3Bsb3QoYWVzKG1vbnRoLCBhcy5udW1lcmljKG1lYW5fdGltZV9yaWRlKSkpKwogIGZhY2V0X2dyaWQofmdlbmRlcikrCiAgZ2VvbV9wb2ludChhZXMoY29sID0gZ2VuZGVyKSkrCiAgZ2VvbV9saW5lKGdyb3VwID0gMSkrCiAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA5MCwgdmp1c3QgPSAwLjUsIGhqdXN0PTEpKQogIGxhYnMoCiAgICB4PSJNb250aCIsCiAgICB5ID0gIkF2ZXJhZ2UgUmlkaW5nIFRpbWUiLAogICAgdGl0bGUgPSAiQXZlcmFnZSByaWRpbmcgdGltZSBmb3IgZWFjaCBtb250aCIsCiAgICBzdWJ0aXRsZSA9ICJmb3IgZWFjaCBnZW5kZXIgTllDXG4iCiAgKQpgYGAKZ2VuZGVyIHdlZWsKYGBge3J9Cm55Y19iaWtlc19zaG9ydCAlPiUgCiAgZ3JvdXBfYnkoZ2VuZGVyKSAlPiUgCiAgaW5kZXhfYnkod2VlaykgJT4lIAogIHN1bW1hcmlzZShtZWFuX3RpbWVfcmlkZSA9IG1lYW4odGltZV9yaWRlKSkgJT4lIAogIGdncGxvdChhZXMod2VlaywgYXMubnVtZXJpYyhtZWFuX3RpbWVfcmlkZSkpKSsKICBmYWNldF93cmFwKH5nZW5kZXIsbmNvbCA9MSwgc2NhbGVzID0gImZyZWVfeSIpKwogIGdlb21fcG9pbnQoYWVzKGNvbCA9IGdlbmRlcikpKwogIGdlb21fbGluZShncm91cCA9IDEpKwogc2NhbGVfeF9jb250aW51b3VzKGJyZWFrcyA9IHNlcSgwLDUyLDUpKSsKICBsYWJzKAogICAgeD0iV2VlayIsCiAgICB5ID0gIkF2ZXJhZ2UgUmlkaW5nIFRpbWUiLAogICAgdGl0bGUgPSAiQXZlcmFnZSByaWRpbmcgdGltZSBmb3IgZWFjaCBtb250aCIsCiAgICBzdWJ0aXRsZSA9ICJmb3IgZWFjaCBnZW5kZXIgTllDXG4iCiAgKQpgYGAKZ2VuZGVyIHdlZWtkYXlzCmBgYHtyfQpueWNfYmlrZXNfc2hvcnQgJT4lIAogIGdyb3VwX2J5KGdlbmRlcikgJT4lIAogIGluZGV4X2J5KHdkYXkpICU+JSAKICBzdW1tYXJpc2UobWVhbl90aW1lX3JpZGUgPSBtZWFuKHRpbWVfcmlkZSkpICU+JSAKICBnZ3Bsb3QoYWVzKHdkYXksIGFzLm51bWVyaWMobWVhbl90aW1lX3JpZGUpKSkrCiAgZmFjZXRfd3JhcCh+Z2VuZGVyLG5jb2wgPTEsIHNjYWxlcyA9ICJmcmVlX3kiKSsKICBnZW9tX3BvaW50KGFlcyhjb2wgPSBnZW5kZXIpKSsKICBnZW9tX2xpbmUoYWVzKGNvbCA9IGdlbmRlciksZ3JvdXAgPSAxKSsKICBsYWJzKAogICAgeD0iV2Vla2RheSIsCiAgICB5ID0gIkF2ZXJhZ2UgUmlkaW5nIFRpbWUiLAogICAgdGl0bGUgPSAiQXZlcmFnZSByaWRpbmcgdGltZSBmb3IgZWFjaCB3ZWVrZGF5cyIsCiAgICBzdWJ0aXRsZSA9ICJmb3IgZWFjaCBnZW5kZXIgTllDXG4iCiAgKQpgYGAKCmBgYHtyfQpueWNfYmlrZXNfc2hvcnQgPC0gbnljX2Jpa2VzX3Nob3J0ICU+JSAgbXV0YXRlKAogIGFnZV9ncm91cCA9IGNhc2Vfd2hlbihhZ2UgPCAxOCB+ICJVbmRlciAxOCIsCiAgICAgICAgICAgICAgICAgICAgICAgIGFnZSA8IDMwIH4iMTggdG8gMzAiLAogICAgICAgICAgICAgICAgICAgICAgICBhZ2UgPCA2MCB+IjMwIHRvIDYwIiwKICAgICAgICAgICAgICAgICAgICAgICAgVFJVRSB+IjYwIGFuZCBhYm92ZSIpCikKYGBgCmFnZV95ZWFyCmBgYHtyfQogbnljX2Jpa2VzX3Nob3J0ICU+JSAKICBtdXRhdGUodGltZV9yaWRlID0gYXMubnVtZXJpYyh0aW1lX3JpZGUpKSAlPiUgCiAgZmlsdGVyKHRpbWVfcmlkZSA8IDE3Ljk0NjE0KSAlPiUgCmdncGxvdCgpICsgCiAgYWVzKGFzLmZhY3RvcihhZ2VfZ3JvdXApLCBhcy5udW1lcmljKHRpbWVfcmlkZSkpKwogIGdlb21fYm94cGxvdChhZXMoY29sID0gYWdlX2dyb3VwKSkgKyAKICBsYWJzKHggPSAiXG5BZ2UgR3JvdXAiLAogICAgIHkgPSAiUmlkaW5nIFRpbWUiLAogICAgIGNvbCA9ICJBZ2UgR3JvdXAiLAogICAgIHRpdGxlID0gIkRpc3RyaWJ1dGlvbiBvZiByaWRlIHRpbWUgaW4gMjAxOCIsCiAgICAgc3VidGl0bGUgPSAid2l0aCA5MCUgb2YgdGhlIGRhdGFcbiIpCmBgYAphZ2UgbW9udGgKYGBge3J9Cm55Y19iaWtlc19zaG9ydCAlPiUgCiAgZ3JvdXBfYnkoYWdlX2dyb3VwKSAlPiUgCiAgaW5kZXhfYnkobW9udGgpICU+JSAKICBzdW1tYXJpc2UobWVhbl90aW1lX3JpZGUgPSBtZWFuKHRpbWVfcmlkZSkpICU+JSAKICBnZ3Bsb3QoYWVzKG1vbnRoLCBhcy5udW1lcmljKG1lYW5fdGltZV9yaWRlKSkpKwogIGZhY2V0X3dyYXAofmFnZV9ncm91cCwgbmNvbCA9IDEsIHNjYWxlcyA9ICJmcmVlX3kiKSsKICBnZW9tX3BvaW50KGFlcyhjb2wgPSBhZ2VfZ3JvdXApKSsKICBnZW9tX2xpbmUoZ3JvdXAgPSAxKSsKICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDkwLCB2anVzdCA9IDAuNSwgaGp1c3Q9MSkpCiAgbGFicygKICAgIHg9Ik1vbnRoIiwKICAgIHkgPSAiQXZlcmFnZSBSaWRpbmcgVGltZSIsCiAgICB0aXRsZSA9ICJBdmVyYWdlIHJpZGluZyB0aW1lIGZvciBlYWNoIG1vbnRoIiwKICAgIHN1YnRpdGxlID0gImZvciBlYWNoIGFnZV9ncm91cCBOWUNcbiIKICApCmBgYAphZ2Ugd2Vla2RheQpgYGB7cn0KbnljX2Jpa2VzX3Nob3J0ICU+JSAKICBncm91cF9ieShhZ2VfZ3JvdXApICU+JSAKICBpbmRleF9ieSh3ZGF5KSAlPiUgCiAgc3VtbWFyaXNlKG1lYW5fdGltZV9yaWRlID0gbWVhbih0aW1lX3JpZGUpKSAlPiUgCiAgZ2dwbG90KGFlcyh3ZGF5LCBhcy5udW1lcmljKG1lYW5fdGltZV9yaWRlKSkpKwogIGZhY2V0X3dyYXAofmFnZV9ncm91cCxuY29sID0xLCBzY2FsZXMgPSAiZnJlZV95IikrCiAgZ2VvbV9wb2ludChhZXMoY29sID0gYWdlX2dyb3VwKSwgc2l6ZSA9IDIpKwogIGdlb21fbGluZShhZXMoY29sID0gYWdlX2dyb3VwKSxncm91cCA9IDEpKwogIGxhYnMoCiAgICB4PSJXZWVrZGF5IiwKICAgIHkgPSAiQXZlcmFnZSBSaWRpbmcgVGltZSIsCiAgICBjb2wgPSAiQWdlIEdyb3VwIiwKICAgIHRpdGxlID0gIkF2ZXJhZ2UgcmlkaW5nIHRpbWUgZm9yIGVhY2ggd2Vla2RheXMiLAogICAgc3VidGl0bGUgPSAiZm9yIGVhY2ggYWdlIGdyb3VwIFxuIgogICkKYGBgCmBgYHtyfQpueWNfYmlrZXNfc2hvcnQgJT4lIAogIGdyb3VwX2J5KGFnZV9ncm91cCkgJT4lIAogIGluZGV4X2J5KHdlZWspICU+JSAKICBzdW1tYXJpc2UobWVhbl90aW1lX3JpZGUgPSBtZWFuKHRpbWVfcmlkZSkpICU+JSAKICBnZ3Bsb3QoYWVzKHdlZWssIGFzLm51bWVyaWMobWVhbl90aW1lX3JpZGUpKSkrCiAgZmFjZXRfd3JhcCh+YWdlX2dyb3VwLG5jb2wgPTEsIHNjYWxlcyA9ICJmcmVlX3kiKSsKICBnZW9tX3BvaW50KGFlcyhjb2wgPSBhZ2VfZ3JvdXApKSsKICBnZW9tX2xpbmUoZ3JvdXAgPSAxKSsKIHNjYWxlX3hfY29udGludW91cyhicmVha3MgPSBzZXEoMCw1Miw1KSkrCiAgbGFicygKICAgIHg9IldlZWsiLAogICAgeSA9ICJBdmVyYWdlIFJpZGluZyBUaW1lIiwKICAgIGNvbCA9ICJBZ2UgR3JvdXAiLAogICAgdGl0bGUgPSAiQXZlcmFnZSByaWRpbmcgdGltZSBmb3IgZWFjaCB3ZWVrIiwKICAgIHN1YnRpdGxlID0gImZvciBlYWNoIGFnZSBncm91cFxuIgogICkKYGBgCmBgYHtyfQpsaWJyYXJ5KGxlYWZsZXQpCmBgYAoKYGBge3J9Cm55Y19iaWtlc19kZiAlPiUgCiAgZmlsdGVyKGJpa2VfaWQgPT0gIjI2MzAxIikgJT4lIApsZWFmbGV0KCkgJT4lIAogIGFkZFRpbGVzKCkgJT4lIAogIGFkZE1hcmtlcnMoCiAgICBsbmcgPSB+c3RhcnRfbG9uZywKICAgIGxhdCA9IH5zdGFydF9sYXQsCiAgICBjbHVzdGVyT3B0aW9ucyA9IG1hcmtlckNsdXN0ZXJPcHRpb25zKCkKICApCmBgYAoKYGBge3J9Cm55Y19iaWtlc19kZiAlPiUgCiAgZmlsdGVyKGJpa2VfaWQgPT0gIjI5NDc3IikgJT4lIApsZWFmbGV0KCkgJT4lIAogIGFkZFRpbGVzKCkgJT4lIAogIGFkZE1hcmtlcnMoCiAgICBsbmcgPSB+c3RhcnRfbG9uZywKICAgIGxhdCA9IH5zdGFydF9sYXQsCiAgICBjbHVzdGVyT3B0aW9ucyA9IG1hcmtlckNsdXN0ZXJPcHRpb25zKCkKICApCmBgYAoKYGBge3J9CiBueWNfYmlrZXNfZGYgJT4lIAogIG11dGF0ZSh3ZWVrID0gd2VlayhzdGFydF90aW1lKSkgJT4lIAogIGZpbHRlcih3ZWVrID09IDQ2KSAlPiUgCiAgbGVhZmxldCgpICU+JSAKICBhZGRUaWxlcygpICU+JSAKICBhZGRNYXJrZXJzKAogICAgbG5nID0gfnN0YXJ0X2xvbmcsCiAgICBsYXQgPSB+c3RhcnRfbGF0LAogICAgY2x1c3Rlck9wdGlvbnMgPSBtYXJrZXJDbHVzdGVyT3B0aW9ucygpCiAgKQpgYGAKYGBge3J9CiBueWNfYmlrZXNfZGYgJT4lIAogIG11dGF0ZSh3ZWVrID0gd2VlayhzdGFydF90aW1lKSkgJT4lIAogIGZpbHRlcih3ZWVrID09IDQyKSAlPiUgCiAgbGVhZmxldCgpICU+JSAKICBhZGRUaWxlcygpICU+JSAKICBhZGRNYXJrZXJzKAogICAgbG5nID0gfmVuZF9sb25nLAogICAgbGF0ID0gfmVuZF9sYXQsCiAgICBjbHVzdGVyT3B0aW9ucyA9IG1hcmtlckNsdXN0ZXJPcHRpb25zKCkKICApCmBgYApuZWFyIHRvIHN0YXRpb25zIAoKCmBgYHtyfQpueWNfYmlrZXNfc2hvcnQgJT4lIAogIGdyb3VwX2J5KGRheSkgJT4lIAogIHN1bW1hcmlzZShtZWFuID0gbWVhbih0aW1lX3JpZGUpKSAlPiUgCiAgYXJyYW5nZShkZXNjKG1lYW4pKQpgYGAKV2UncmUgbWlkLXdheSB0aHJvdWdoIFdvbWVuJ3MgQmlrZSBNb250aCEgb2N0b2JlcgpEaWQgeW91IGtub3cgb25seSBhIHF1YXJ0ZXIgb2YgYWxsIGJpa2UgdHJpcHMgaW4gdGhlIFUuUy4gYXJlIHRha2VuIGJ5IHdvbWVuPyBBdCBDaXRpIEJpa2UsIHdlJ3JlIGRlZGljYXRlZCB0byBjaGFuZ2luZyB0aGlzLiAKVGhpcyBtb250aCB3ZSdyZSBnaXZpbmcgYWxsIG5ldyByaWRlcnMgdGhlaXIgZmlyc3QgdHJpcCBmcmVlIHVzaW5nIGNvZGUgR0lSTFVQMTgsIGFuZCBkb25hdGluZyAkMSBmcm9tIGVhY2ggb2YgdGhlc2UgcmlkZXMgdG8gR2lybCBVcCdzIFNjaG9vbEN5Y2xlIHByb2dyYW0gdG8gaGVscCBwcm92aWRlIGJpa2VzIHRvIGdpcmxzIGFyb3VuZCB0aGUgd29ybGQgc28gdGhleSBjYW4gc2FmZWx5IGFjY2VzcyBlZHVjYXRpb24uCkpvaW4gdXMgaW4gZW5jb3VyYWdpbmcgbW9yZSBsYWRpZXMgdG8gZ2V0IG9uIGJpa2VzIGFuZCBnaXZlIGJhY2sgdG8gYSBncmVhdCBjYXVzZSB3aGlsZSBkb2luZyBpdC4gCgoKCmBgYHtyfQoKIG55Y19iaWtlc19kZiAlPiUgCiAgbXV0YXRlKHdlZWsgPSB3ZWVrKHN0YXJ0X3RpbWUpKSAlPiUgCiAgZmlsdGVyKHdlZWsgPT0gNCkgJT4lIAogIGxlYWZsZXQoKSAlPiUgCiAgYWRkVGlsZXMoKSAlPiUgCiAgYWRkTWFya2VycygKICAgIGxuZyA9IH5lbmRfbG9uZywKICAgIGxhdCA9IH5lbmRfbGF0LAogICAgY2x1c3Rlck9wdGlvbnMgPSBtYXJrZXJDbHVzdGVyT3B0aW9ucygpCiAgKQpgYGAKYGBgCgo=